package ModelAndController;

import java.io.File;

/*
 * A program indulásakor elinduló osztály.Tartalmazza a main() függvényt,
 * a menükezelést és létrehozza a Model osztályt a menüben szerzett információk alapján.
 */
public class Controller {
	
	//int limit=100;
	//referencia a Model példányára
	Model model;
	//referencia a View példányára
	View view;
	Window.View windowView;
	//konstruktor,model és view létrehozása,valamint a parancsértelmező elindítása
	public Controller(){
		model = new Model();
		windowView = new Window.View(this);
	}
	//main függvény,benne a controller létrehozása
	public static void main(String[] args) {
		new Controller();
	}
	//create parancs a parancsértelmezőből
	public void create(String fileName){
		try{
			model.readFromFile(fileName);
			windowView.resetAllValues();
			isCircuitLoaded();
			setAllVariablesToWindowView();
			File file = new File(fileName);
			windowView.setFileName(file.getName() );
			windowView.regenerateWindow();
		}catch(Exception e){
			windowView.catchException(e);
		}
	}
	public void isCircuitLoaded(){
		boolean circuitState = model.isCircuitLoaded();
		windowView.setIsCircuitLoaded(circuitState);
	}
	//getSwitch parancs a parancsértelmezőből
	public void getSwitch(){
		try{
			model.getAllValueOfSwitches();
			view.print( model.getBuffer() );
		}catch(Exception e){
			windowView.catchException(e);
		}
	}
	//setSwitch parancs a parancsértelmezőből
	public void setSwitch(int switchIndex){
		try{
			model.setValueOfActualSwitch(switchIndex);
			//view.print( model.getBuffer() );
		}catch(Exception e){
			windowView.catchException(e);
		}
	}
	//getSignal parancs a parancsértelmezőből
	public void getSignal(){
		try{
			model.getAllValueOfSignals();
			view.print( model.getBuffer() );
		}catch(Exception e){
			windowView.catchException(e);
		}
	}
	//setSignal parancs a parancsértelmezőből
	public void setSignal(int signalID, int[] values){
		try{
			model.setValuesOfActualSignalGenerator(signalID, values);
			//view.print( model.getBuffer() );
		}catch(Exception e){
			windowView.catchException(e);
		}
	}
	//getDisplay parancs a parancsértelmezőből
	public void getDisplay(){
		try{
			model.getAllDisplay();
			view.print(model.getBuffer());
		}catch(Exception e){
			windowView.catchException(e);
		}
	}
	//getScope parancs a parancsértelmezőből (részletes nézet)
	public void getScope(int index){
		try{
			model.getActualScope( index );
			//view.print( model.getBuffer() );
		}catch(Exception e){
			windowView.catchException(e);
		}
	}
	//getScope parancs a parancsértelmezőből (összegző nézet)
	public void getScope(){
		try{
			model.getAllScope();
			//view.print( model.getBuffer() );
		}catch(Exception e){
			windowView.catchException(e);
		}
	}
	//step parancs a parancsértelmezőből
	public void step(){
		try{
			model.startSchedule(false, null);
			//view.print( model.getBuffer() );
		}catch(Exception e){
			windowView.catchException(e);
		}
	}
	//stepList parancs a parancsértelmezőből
	public void stepList(){
		try{
			model.startSchedule(true, null);
			view.print( model.getBuffer() );
		}catch(Exception e){
			windowView.catchException(e);
		}
	}
	//stepList parancs a parancsértelmezőből (kompozitok listázása)
	public void stepList(int[] composites){
		try{
			model.startSchedule(true, composites);
			view.print( model.getBuffer() );
		}catch(Exception e){
			windowView.catchException(e);
		}
	}
	//step parancs a parancsértelmezőből (több ciklus egyszerre)
	public void step(int step){
		try{
			setAllVariablesToModel();
			model.schedule(step);			
			setAllVariablesToWindowView();
			windowView.regenerateWindow();
		}catch(Exception e){
			windowView.catchException(e);
		}
	}
	//setStableLimit parancs a parancsértelmezőből
	public void setStableLimit(int value){
		model.setNbOfMaxUpdates(value);
		view.print( model.getBuffer() );
	}
	
	//Setting all windowView value to Model
	private void setAllVariablesToModel(){
		try{
			//Checking switch values
			int[] windowSwitchValues = windowView.getSwitches();
			int[] modelSwitchValues = model.getAllValueOfSwitches();
			
			if( windowSwitchValues != null){
				for(int act = 0; act < windowSwitchValues.length; act++){
					if( windowSwitchValues[act] != modelSwitchValues[act] )
						setSwitch(act);
				}
			}
			
			//Checking Signalvalues
			int[][] windowSignalValues = windowView.getAllValuesOfSignal();
			int[][] modelSignalValues = model.getAllValueOfSignals();
			
			if(windowSignalValues != null){
				for(int act = 0; act < windowSignalValues.length; act++){
					boolean valueIsValide = true;
				
					if(windowSignalValues[act].length != modelSignalValues[act].length)
						valueIsValide = false;
					else
						for(int actVal = 0; actVal < windowSignalValues[act].length; actVal++)
							if( windowSignalValues[act][actVal] != modelSignalValues[act][actVal]){
								valueIsValide = false;
								break;
							}
					if( !valueIsValide )
						setSignal(act, windowSignalValues[act]);
				}
			}
			
		}catch(Exception e){
			windowView.catchException(e);
		}
	}
	
	//Setting all model values to windowView
	private void setAllVariablesToWindowView(){
		try{
			windowView.setSwitches(model.getAllValueOfSwitches());
			windowView.setDisplay(model.getAllDisplay());
			windowView.setSignal(model.getActValuesOfSignals());
			windowView.setAllValuesOfSignal(model.getAllValueOfSignals());
			windowView.setAllValuesOfSignal(model.getAllValueOfSignals());
			windowView.setStableScopeValues(model.getAllScope());
			windowView.setTemporalScopeValues(model.getAllDeltaValueOfScopes());
		}catch(Exception e){
			windowView.catchException(e);
		}
	}
}